package com.java.model.singleton;

/**
 * DCL (double check lock)
 * DCL 双重检查，需要注意的是instance字段需要加上volatile修饰，因为instance = new DCLSingleton()并不是一个原子操作，
 * 从字节码上看，一个涉及到4个操作(new, dup, invokespecial, putstatic)，其中invokespecial是调用构造函数进行初始化，
 * putstatic是讲new出来的引用值赋值给instance，这两个操作没有相互依赖关系。
 * 如果不加volatile修饰，在多线程并发访问的时候，可能导致重排序，先执行putstatic，后执行invokespecial，在这两个操作之间，
 * 如果另外一个线程执行getInstance，此时instance == null是不成立的，直接返回了instance，这样就获取到一个没有初始化的单例对象，
 * 后面可能会导致意外的结果。
 *
 * @author wangning
 * @create 2021-04-20 14:48
 */
public class DCLSingleton {
	//DCL 双重检查
	private static volatile DCLSingleton instance;

	private DCLSingleton() {
	}

	public static DCLSingleton getInstance() {
		if (instance == null) {
			synchronized (DCLSingleton.class) {
				if (instance == null) {
					instance = new DCLSingleton();
				}
			}
		}
		return instance;
	}
}
